/**
 * Box class
 * @author Minh-Tuan
 *
 */

import java.awt.*;

public class Box {
	//constant the spaces between the dots (width and height of the boxes when draw the box)
	public static final int SPACE = 25;
	
	//margin of the boxes when draw the first box
	public static final int MARGIN = 50;
	
	//radius of each dot
	public static final int DOT_RADIUS = 10;
	
	public boolean north;
	public boolean south;
	public boolean east;
	public boolean west;
	
	public int firstDot;
	public int secondDot;
	public int thirdDot;
	public int fourthDot;
	
	private char owner;
	
	//the boxes in north, south, east and west for easy to set the borders
	private Box northBox;
	private Box southBox;
	private Box eastBox;
	private Box westBox;
	
	//position of the box
	public int row;
	public int column;
	
	private Board board;
	
	public Box(int row, int column, Board board)
	{
		this.row = row;
		this.column = column;
		this.board = board;
		
		north = east = south = west = false;
		owner = 'N';
	}
	
	//copy the box
	public Box(Box box, Board board)
	{
		this.board = board;
		this.row = box.row;
		this.column = box.column;
		
		this.north = box.north;
		this.east = box.east;
		this.south = box.south;
		this.west = box.west;
		this.owner = box.owner;
	}
	
	/**
	 * This method is called after the board has 2 dim array of boxes
	 * Call this method to setup the boxes around this box
	 */
	public void init()
	{
		//init the border boxes
		
		//if not the first row, set north box
		if (row != 0)
			this.northBox = board.getBoxes()[row - 1][column];
		
		//if not the last column, set east box
		if (column < board.getWidth() - 2)
		{
			this.eastBox = board.getBoxes()[row][column + 1];
		}
		
		//if not the last row, set south box
		if (row < board.getHeight() - 2)
		{
			this.southBox = board.getBoxes()[row + 1][column];
		}
		
		//if not the first column, set west box
		if (column > 0)
		{
			this.westBox = board.getBoxes()[row][column - 1];
		}
		
		this.firstDot = this.row * this.board.getWidth() + this.column + 1;
		this.secondDot = this.row * this.board.getWidth() + this.column + 1 + 1;
		this.thirdDot = this.row * this.board.getWidth() + this.column + 1 + this.board.getWidth() + 1;
		this.fourthDot = this.row * this.board.getWidth() + this.column + 1 + this.board.getWidth();
	}

	public boolean getNorth() {
		return north;
	}

	public void setNorth(boolean value, char player) {
		
		if (value == false)
		{
			setOwner('N');
			this.north = false;
		}
		else
		{
			if (this.north != value)
				this.north = value;
			
			if (north && east && south && west)
				setOwner(player);
		}
		
		if (northBox != null && northBox.getSouth() != value)
		{
			northBox.setSouth(value, player);
		}
	}

	public boolean getSouth() {
		return south;
	}

	public void setSouth(boolean value, char player) {		
		
		if (value == false)
		{
			setOwner('N');
			this.south = false;
		}
		else
		{
			if (this.south != value)
				this.south = value;
			
			if (north && east && south && west)
				setOwner(player);
		}
		
		if (southBox != null && southBox.getNorth() != value)
		{
			southBox.setNorth(value, player);
		}
	}

	public boolean getEast() {
		return east;
	}

	public void setEast(boolean value, char player) {
		
		if (value == false)
		{
			setOwner('N');
			this.east = false;
		}
		else
		{
			if (this.east != value)
				this.east = value;
			
			if (north && east && south && west)
				setOwner(player);
		}
		
		if (eastBox != null && eastBox.getWest() != value)
		{
			eastBox.setWest(value, player);
		}
	}

	public boolean getWest() {
		return west;
	}

	public void setWest(boolean value, char player) {
		
		if (value == false)
		{
			setOwner('N');
			this.west = false;
		}
		else
		{
			if (this.west != value)
				this.west = value;
			
			if (north && east && south && west)
				setOwner(player);
		}
		
		if (westBox != null && westBox.getEast() != value)
		{
			westBox.setEast(value, player);
		}
	}

	public char getOwner() {
		return owner;
	}

	public void setOwner(char owner) {
		this.owner = owner;
	}

	public Box getNorthBox() {
		return northBox;
	}

	public void setNorthBox(Box northBox) {
		this.northBox = northBox;
	}

	public Box getSouthBox() {
		return southBox;
	}

	public void setSouthBox(Box southBox) {
		this.southBox = southBox;
	}

	public Box getEastBox() {
		return eastBox;
	}

	public void setEastBox(Box eastBox) {
		this.eastBox = eastBox;
	}

	public Box getWestBox() {
		return westBox;
	}

	public void setWestBox(Box westBox) {
		this.westBox = westBox;
	}
	
	//draw the box
	public void draw(Graphics g)
	{
		//calculate where is the top left position (in pixels)
		int left = MARGIN + SPACE * column;
		int top = MARGIN + SPACE * row;
		
		//set color to blue for the dots
		g.setColor(new Color(65, 105, 225));
		
		//draw the 4 dots and the number of the dots
		g.drawString("" + this.firstDot, left + 10, top + 20);
		g.fillOval(left, top, DOT_RADIUS, DOT_RADIUS);
		g.drawString("" + this.secondDot, left + SPACE + 10, top + 20);
		g.fillOval(left + SPACE, top, DOT_RADIUS, DOT_RADIUS);
		g.drawString("" + this.thirdDot, left + SPACE + 10, top + SPACE + 20);
		g.fillOval(left + SPACE, top + SPACE, DOT_RADIUS, DOT_RADIUS);
		g.drawString("" + this.fourthDot, left + 10, top + SPACE + 20);
		g.fillOval(left, top + SPACE, DOT_RADIUS, DOT_RADIUS);
		
		//set color to orange to draw lines
		g.setColor(new Color(255, 69, 0));
		
		//if the north is set, draw the north
		if (this.north)
		{
			g.drawLine(left, top, left + SPACE, top);
		}
		
		//if the east if set, draw the east
		if (this.east)
		{
			g.drawLine(left + SPACE, top, left + SPACE, top + SPACE);
		}
		
		//if the south is set, draw the south
		if (this.south)
		{
			g.drawLine(left + SPACE, top + SPACE, left, top + SPACE);
		}
		
		//if the west is set, draw the west
		if (this.west)
		{
			g.drawLine(left, top + SPACE, left, top);
		}
		
		//if the box owned by 1 of the player, write the player inital
		if (this.north && this.east && this.south && this.west)
		{
			//if the player own the box, set color to dark green
			if (this.owner == 'P')
				g.setColor(new Color(0, 100, 0));
			else //if the opponent own the box, set color to black
				g.setColor(new Color(0, 0, 0));
			
			//write the initial of the owner
			g.drawString("" + getOwner(), left + SPACE / 2, top + SPACE / 2);
		}
	}
	
	/**
	 * The board will delegate the move method to the box's move method
	 * @param firstDot: number of the first dot
	 * @param secondDot: number of the second dot
	 * @param player: character represent the player
	 * @return 0: made the move ok, 1: won the box, -1: can't make move
	 */
	public int move(int firstDot, int secondDot, char player)
	{
		int result = -1;
		//if north
		if ((this.firstDot == firstDot && this.secondDot == secondDot) || (this.firstDot == secondDot && this.secondDot == firstDot))
		{
			//can set the move
			result = 0;
			
			//set the north border
			if (this.north != true)
				setNorth(true, player);
			else
				result = -1;
			
			//if a box made, return 1
			if (this.owner != 'N')
				result = 1;
			else
				if (this.northBox != null)
					if (this.northBox.owner != 'N')
						result = 1;
		}
		else if ((this.secondDot == firstDot && this.thirdDot == secondDot) || (this.secondDot == secondDot && this.thirdDot == firstDot))
		{
			//can set the move
			result = 0;
			
			//set the east border
			if (this.east != true)
				setEast(true, player);
			else
				result = -1;
			
			//if a box made, return 1
			if (this.owner != 'N')
				result = 1;
			else
				if (this.eastBox != null)
					if (this.eastBox.owner != 'N')
						result = 1;
		}
		else if ((this.thirdDot == firstDot && this.fourthDot == secondDot) || (this.thirdDot == secondDot && this.fourthDot == firstDot))
		{
			//can set the move
			result = 0;
			
			//set the south border
			if (this.south != true)
				setSouth(true, player);
			else
				result = -1;
			
			//if a box made, return 1
			if (this.owner != 'N')
				result = 1;
			else
				if (this.southBox != null)
					if (this.southBox.owner != 'N')
						result = 1;
		}
		else if ((this.fourthDot == firstDot && this.firstDot == secondDot) || (this.fourthDot == secondDot && this.firstDot == firstDot))
		{
			//can set the move
			result = 0;
			
			//set the west border
			if (this.west != true)
				setWest(true, player);
			else
				result = -1;
			
			//if a box made, return 1
			if (this.owner != 'N')
				result = 1;
			else
				if (this.westBox != null)
					if (this.westBox.owner != 'N')
						result = 1;
		}
				
		return result;
	}
	
	/**
	 * The board will delegate the move method to the box's move method
	 * @param firstDot: number of the first dot
	 * @param secondDot: number of the second dot
	 * @param player: character represent the player
	 * @return true if redo successfully, false if not success
	 */
	public boolean redo(int firstDot, int secondDot, char player)
	{
		boolean r = false;
		
		//if north
		if ((this.firstDot == firstDot && this.secondDot == secondDot) || (this.firstDot == secondDot && this.secondDot == firstDot))
		{
			setNorth(false, player);
			r = true;
		}
		else if ((this.secondDot == firstDot && this.thirdDot == secondDot) || (this.secondDot == secondDot && this.thirdDot == firstDot))
		{
			setEast(false, player);
			r = true;
		}
		else if ((this.thirdDot == firstDot && this.fourthDot == secondDot) || (this.thirdDot == secondDot && this.fourthDot == firstDot))
		{
			setSouth(false, player);
			r = true;
		}
		else if ((this.fourthDot == firstDot && this.firstDot == secondDot) || (this.fourthDot == secondDot && this.firstDot == firstDot))
		{
			setWest(false, player);
			r = true;
		}
		
		return r;
	}
}